use super::*;

// Trait for converting types to function arguments
pub trait ArgsBuilder {
	fn into_args(self, env: &Env) -> Result<'static, Vec<sys::napi_value>>;
	fn arg_count(&self) -> usize;
}

// Implementation for empty tuple (no arguments)
impl ArgsBuilder for () {
	fn into_args(self, _env: &Env) -> Result<'static, Vec<sys::napi_value>> {
		Ok(vec![])
	}

	fn arg_count(&self) -> usize {
		0
	}
}

// Implementation for Vec of arguments
impl<T: IntoNapi> ArgsBuilder for Vec<T> {
	fn into_args(self, env: &Env) -> Result<'static, Vec<sys::napi_value>> {
		let mut args = Vec::with_capacity(self.len());
		for arg in self {
			args.push(arg.into_napi(env)?.raw());
		}
		Ok(args)
	}

	fn arg_count(&self) -> usize {
		self.len()
	}
}

// Macro for implementing IntoArgs for tuples of different lengths
macro_rules! tuple_impl_serial {
	($len:tt $($n:tt $name:ident)*) => {
		impl<$($name:IntoNapi,)*> ArgsBuilder for ($($name,)*) {
			fn into_args(self, _env: &Env) -> Result<'static, Vec<sys::napi_value>> {
				Ok(vec![$(self.$n.into_napi(_env)?.raw()),*])
			}

			fn arg_count(&self) -> usize {
				$len
			}
		}
	}
}

// Implementations for tuples of length 1 to 20
tuple_impl_serial!(1 0 A);
tuple_impl_serial!(2 0 A 1 B);
tuple_impl_serial!(3 0 A 1 B 2 C);
tuple_impl_serial!(4 0 A 1 B 2 C 3 D);
tuple_impl_serial!(5 0 A 1 B 2 C 3 D 4 E);
tuple_impl_serial!(6 0 A 1 B 2 C 3 D 4 E 5 F);
tuple_impl_serial!(7 0 A 1 B 2 C 3 D 4 E 5 F 6 G);
tuple_impl_serial!(8 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H);
tuple_impl_serial!(9 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I);
tuple_impl_serial!(10 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J);
tuple_impl_serial!(11 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K);
tuple_impl_serial!(12 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L);
tuple_impl_serial!(13 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L 12 M);
tuple_impl_serial!(14 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L 12 M 13 N);
tuple_impl_serial!(15 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L 12 M 13 N 14 O);
tuple_impl_serial!(16 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L 12 M 13 N 14 O 15 P);
tuple_impl_serial!(17 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L 12 M 13 N 14 O 15 P 16 Q);
tuple_impl_serial!(18 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L 12 M 13 N 14 O 15 P 16 Q 17 R);
tuple_impl_serial!(19 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L 12 M 13 N 14 O 15 P 16 Q 17 R 18 S);
tuple_impl_serial!(20 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L 12 M 13 N 14 O 15 P 16 Q 17 R 18 S 19 T);
